/*
 * Shader.java
 *
 * Created on September 22, 2007, 9:13 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package Raytracing.Shaders;

import Raytracing.BRDF.BRDF;
import Raytracing.BRDF.LambertBRDF;
import Raytracing.Ray;
import processing.core.*;

public class Shader extends Material {

    public float emit = 0;
    public BRDF[] brdf;
    public float[] weight;

    public Shader(String name) {
        this(name, new PVector(.5f, .5f, .5f));

    }

    protected void setFillColor(PVector fillColor) {
        this.fillColor = fillColor;
        fill = 0xff000000 | ((int) (fillColor.x * 255) << 16)
                | ((int) (fillColor.y * 255) << 8)
                | (int) (fillColor.z * 255);
    }

    public Shader(String name, PVector fillColor) {
        this.fillColor = fillColor;
        fill = 0xff000000 | ((int) (fillColor.x * 255) << 16)
                | ((int) (fillColor.y * 255) << 8)
                | (int) (fillColor.z * 255);

        setName(name);
        brdf = new BRDF[1];
        brdf[0] = new LambertBRDF(new SolidTexture(fillColor));
        weight = new float[1];
        weight[0] = 1.f;
    }

    public Shader(String name, float r, float g, float b) {
        this(name, new PVector(r, g, b));


    }

    protected void addBRDF(BRDF brdf) {
        weight = new float[1];
        this.brdf = new BRDF[1];

        this.brdf[0] = brdf;
        weight[0] = 1f;
    }

    public Shader(String name, float r, float g, float b, BRDF brdf) {
        this(name, r, g, b);
        this.emit = emit;
        setName(name);
        addBRDF(brdf);
    }

    public Shader(String name, float r, float g, float b, BRDF brdf, BRDF brdf2) {
        this(name, r, g, b);
        this.emit = emit;

        weight = new float[2];
        this.brdf = new BRDF[2];

        this.brdf[0] = brdf;
        weight[0] = .5f;

        this.brdf[1] = brdf2;
        weight[1] = .5f;
    }
    /*
     * Returns the PDF of the selected sample
     */

    public float sampleReflectance(PVector outgoing, Ray sample,
            PVector normal, PVector BRDF,
            float tu, float tv, PVector u, PVector v,
            float u1, float u2) {



        int which = (int) (Math.random() * brdf.length);

        float ret = (1.f / brdf.length) * brdf[which].sampleReflectance(outgoing, sample, normal, BRDF, tu, tv, u, v, u1, u2);

        return ret;
    }

    public PVector getReflectance(PVector incoming, PVector outgoing, PVector normal, float tu, float tv, PVector u, PVector v) {

        PVector ret = new PVector();

        for (int i = 0; i < brdf.length; i++) {
            ret.add(PVector.mult(brdf[i].getReflectance(incoming, outgoing, normal, tu, tv, u, v), weight[i]));
        }

        return ret;
    }
}
